<?php
/**
 * tinymvc超轻量级PHP开发框架
 *
 * @author    Lansn
 * @copyright Copyright (c) 2024-2025
 * @license   tinymvc 遵循Apache2开源协议发布，需保留开发者信息。
 * @link      http://173654757.xyz
 */

namespace tinymvc\core;

use tinymvc\core\Lang;
use tinymvc\core\Request;
use tinymvc\core\Response;
use Flight;

class Controller
{
    protected string $module;
    protected string $controller;
    protected string $action;

    protected $session;
    protected $request;
    protected $response;

    protected array $vars = [];

    // 存储布局路径（可为null，表示使用模块默认layout.phtml）
    protected ?string $layout = null;

    public function __construct(string $module, string $controller, string $action)
    {
        $this->module     = $module;
        $this->controller = $controller;
        $this->action     = $action;

        $this->session  = Flight::session();
        $this->request  = new Request();
        $this->response = new Response();

        // 多国语言支持
        Lang::init($module);

        // 调用可被子类覆盖的初始化方法
        $this->initialize();
    }

    protected function initialize()
    {
        // 默认无操作，供子类覆盖
    }

    /**
     * 设置布局文件路径，传入 false 表示关闭布局
     */
    public function setLayout(string|bool $layoutPath): void
    {
        $this->layout = $layoutPath;
    }

    protected function getViewPath(string $viewName): string
    {
        $module = $this->module;
        $controller = strtolower(str_replace('Controller', '', (new \ReflectionClass($this))->getShortName()));
        return APP_PATH . "$module/view/$controller/$viewName.phtml";
    }

    protected function getLayoutPath(): ?string
    {
        if ($this->layout === null) {
            // 使用模块默认layout.phtml
            $module = $this->module;
            $defaultLayout = APP_PATH . "$module/view/layout.phtml";
            return file_exists($defaultLayout) ? $defaultLayout : null;
        } elseif ($this->layout === false) {
            // false 表示关闭布局
            return null;
        } else {
            // 自定义布局路径
            return file_exists($this->layout) ? $this->layout : null;
        }
    }

    public function assign(string|array $key, $value = null): void
    {
        if (is_array($key)) {
            foreach ($key as $k => $v) {
                $this->vars[$k] = $v;
            }
        } else {
            $this->vars[$key] = $value;
        }
    }

    public function setvar(string|array $key, $value = null): void
    {
        if (is_array($key)) {
            foreach ($key as $k => $v) {
                $this->vars[$k] = $v;
            }
        } else {
            $this->vars[$key] = $value;
        }
    }

    public function display(string|array $vars = '', array $var2 = []): void
    {
        if (is_array($vars)) {
            $this->assign($vars);
            $view = '';
        } else {
            $view = $vars;
        }

        if (is_array($var2)) {
            $this->assign($var2);
        }
        
        if (empty($view)) {
            $viewFile = APP_PATH . "/{$this->module}/view/" . strtolower($this->controller) . "/{$this->action}.phtml";
        } else {
            $parts = explode('/', $view);

            if (count($parts) === 1) {
                $viewFile = APP_PATH . "/{$this->module}/view/" . strtolower($this->controller) . "/{$parts[0]}.phtml";
            } elseif (count($parts) === 3) {
                [$module, $controller, $viewName] = $parts;
                $viewFile = APP_PATH . "/{$module}/view/{$controller}/{$viewName}.phtml";
            } else {
                if (count($parts) === 2) {
                    [$first, $second] = $parts;
                    $tryPath1 = APP_PATH . "/{$first}/view/" . strtolower($this->controller) . "/{$second}.phtml";
                    if (file_exists($tryPath1)) {
                        $viewFile = $tryPath1;
                    } else {
                        $viewFile = APP_PATH . "/{$this->module}/view/{$first}/{$second}.phtml";
                    }
                } else {
                    throw new \Exception("Invalid view parameter format: $view");
                }
            }
        }

        if (!file_exists($viewFile)) {
            throw new \Exception("View file not found: $viewFile");
        }

        extract($this->vars, EXTR_SKIP);

        ob_start();
        include $viewFile;
        $content = ob_get_clean();

        $layout = $this->getLayoutPath();

        if ($layout && file_exists($layout)) {
            include $layout;
        } else {
            echo $content;
        }
    }

    public function getModule()
    {
        return strtolower($this->module);
    }

    public function getController()
    {
        return strtolower($this->controller);
    }

    public function getAction()
    {
        return strtolower($this->action);
    }

}
